﻿using Furion.CMS.Core;
using Furion.CMS.Core.Handlers;
using Furion.CMS.Domain;
using Furion.DatabaseAccessor;
using Furion.DependencyInjection;
using Furion.EventBus;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Application
{
    /// <summary>
    /// 数据审计事件订阅
    /// </summary>
    public class DbAuditEventSubscriber : IEventSubscriber, ISingleton
    {
        private readonly ILogger<DbAuditEventSubscriber> _logger;

        public DbAuditEventSubscriber(ILogger<DbAuditEventSubscriber> logger)
        {
            _logger = logger;
        }

        [EventSubscribe(EventIdConsts.DbAudit)]
        public async Task CreateDbAudit(EventHandlerExecutingContext context)
        {
            _logger.LogInformation($"事件[{EventIdConsts.DbAudit}] 开始处理");
            if (context.Source is DbAuditEventSource dbAuditEvent && dbAuditEvent.Payload is List<DbAuditContent> changes)
            {
                var _auditLogRepository = App.GetRequiredService<IRepository<AuditLog>>();
                _logger.LogInformation($"事件[{EventIdConsts.DbAudit}] 解析数据");
                int.TryParse(dbAuditEvent.UserId, out var uid);
                var rowKey = string.Empty;
                // 优先进行处理程序处理
                if (dbAuditEvent.TransitionHandle != null)
                {// 查询关联数据
                    if (Activator.CreateInstance(dbAuditEvent.TransitionHandle) is AuditLogFormatHandler formatHandler)
                    {
                        rowKey = formatHandler.GetRowKey(_auditLogRepository.Context, dbAuditEvent.RowKey);
                    }
                }
                else
                {
                    if (dbAuditEvent.RowKey is Enum em) rowKey = em.GetDescription();
                    else rowKey = dbAuditEvent.RowKey?.ToString();
                }

                // 其他值转换处理
                foreach(var change in changes)
                {
                    if (change.TransitionHandle != null 
                        && Activator.CreateInstance(change.TransitionHandle) is AuditLogFormatHandler formatHandler)
                    {
                        var changeValues = formatHandler.GetChangeValue(_auditLogRepository.Context, change.OldValue, change.NewValue);
                        change.OldValue = changeValues[0];
                        change.NewValue = changeValues[1];
                    }
                }

                await _auditLogRepository.InsertNowAsync(new AuditLog
                {
                    Table = dbAuditEvent.Table,
                    AppName = dbAuditEvent.AppName,
                    Operate = dbAuditEvent.Operate,
                    UserId = uid,
                    IPAddress = dbAuditEvent.IPAddress,
                    RowKey = rowKey,
                    RowContent = changes.ToArray(),
                    CreatedTime = dbAuditEvent.CreatedTime
                });
                _logger.LogInformation($"事件[{EventIdConsts.DbAudit}] 数据入库成功");
            }
            _logger.LogInformation($"事件[{EventIdConsts.DbAudit}] 处理完成");
        }
    }
}
